package com.shensi.adminCollect.service.station.impl;

import com.alibaba.fastjson.JSONObject;
import com.shensi.common.core.exception.BaseException;
import com.shensi.common.core.utils.StringUtils;
import com.shensi.adminCollect.domain.station.*;
import com.shensi.adminCollect.domain.station.dto.PhysicalCardListDto;
import com.shensi.adminCollect.enums.station.*;
import com.shensi.adminCollect.mapper.station.PhysicalCardMapper;
import com.shensi.adminCollect.service.station.*;
import com.shensi.adminCollect.utils.station.SnowFlakeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

@Service("physicalCardServiceImpl")
@Slf4j
public class PhysicalCardServiceImpl implements IPhysicalCardService {

    @Autowired
    private PhysicalCardMapper physicalCardMapper;

    @Autowired
    private IPhysicalCardBalanceService physicalCardBalanceService;

    @Autowired
    private IEnterpriseService enterpriseService;

    @Autowired
    private IStationService stationService;

    @Autowired
    private CardBatchService cardBatchService;

    // 实体卡A密钥，16进制,必须是12位
    @Value("${physicalCard.secretKeyA}")
    private String SECRET_KEY_A;

    //实体卡B密钥，16进制,必须是12位
    @Value("${physicalCard.secretKeyB}")
    private String SECRET_KEY_B;

    @Override
    public PhysicalCard selectPhysicalCard(String physicalCardNo) {
        if(StringUtils.isNull(physicalCardNo)){
            throw new BaseException("qujia-customer","PhysicalCardServiceImpl实体卡卡号不能为空");
        }

        return physicalCardMapper.selectByPrimaryKey(physicalCardNo);
    }

    @Override
    public List<PhysicalCard> selectPhysicalCardList(PhysicalCardListDto physicalCardDto) {
        // 一张实体卡绑定多个油站， 油站id 和 油站名按照 , 拼接
        List<PhysicalCard> physicalCardList = physicalCardMapper.selectPhysicalCardList(physicalCardDto);
        log.info("physicalCardList:[{}]",JSONObject.toJSONString(physicalCardList));
        return physicalCardList;
    }

    @Override
    @Transactional
    public String addPhysicalCard(PhysicalCard physicalCard) {
        if(Objects.isNull(physicalCard)){
            throw new BaseException("qujia-customer","PhysicalCardServiceImpl没有新增的实体卡信息");
        }

        if(StringUtils.isNotEmpty(physicalCard.getUserPhone()) && Objects.nonNull(physicalCard.getEnterpriseId())){
            PhysicalCard newPhysicalCard = this.selectByEnterpriseIdAndPhone(physicalCard.getEnterpriseId(), physicalCard.getUserPhone());
            if(Objects.nonNull(newPhysicalCard)){
                throw new BaseException("qujia-customer","PhysicalCardServiceImpl手机号不能重复");
            }
        }

        long physicalCardNo;
        if(StringUtils.isNotEmpty(physicalCard.getPhysicalCardNo())){
            physicalCard.setPhysicalCardNo(physicalCard.getPhysicalCardNo());
            physicalCardNo = Long.valueOf(physicalCard.getPhysicalCardNo());
        }else {
            //新增实体卡  生成卡号
            physicalCardNo = SnowFlakeUtil.getDefaultSnowFlakeId();
            physicalCard.setPhysicalCardNo(String.valueOf(physicalCardNo));
        }

        // 获取油企名和油站名
        if(Objects.nonNull(physicalCard.getEnterpriseId())) {
            physicalCard.setEnterpriseName(getEnterpriseName(physicalCard.getEnterpriseId()));
        }

        if(StringUtils.isNotEmpty(physicalCard.getStationId())) {
            physicalCard.setStationName(getStationName(physicalCard.getStationId()));
        }

        physicalCard.setCreateTime(new Date());
        physicalCard.setCardStatus(CardStatusEnum.NORMAL.getCode());
        physicalCard.setEquipmentNo("0");
        log.info("新增实体卡，PhysicalCardServiceImpl.addPhysicalCard: [{}]", JSONObject.toJSONString(physicalCard));
        if(Objects.isNull(physicalCard.getIsAdd()) || 1 != physicalCard.getIsAdd()) {
            physicalCardMapper.insertSelective(physicalCard);
        }

        // 是否充值 新增卡金额>0 即充值
        if(Objects.nonNull(physicalCard.getPhysicalCardAmount())
                && (physicalCard.getPhysicalCardAmount().signum() > 0) &&
                (Objects.isNull(physicalCard.getIsAdd()) || 1 != physicalCard.getIsAdd())){
            recharge(physicalCard);
        }
        return String.valueOf(physicalCardNo);
    }

    @Override
    public int updatePhysicalCard(PhysicalCard physicalCard) {
        if(Objects.isNull(physicalCard) || StringUtils.isEmpty(physicalCard.getPhysicalCardNo())){
            throw new BaseException("qujia-customer","PhysicalCardServiceImpl覆盖实体卡信息请求参数异常");
        }

        physicalCard.setUpdateTime(new Date());
        log.info("修改实体卡，PhysicalCardServiceImpl.updatePhysicalCard: [{}]", JSONObject.toJSONString(physicalCard));
        return physicalCardMapper.updateByPrimaryKeySelective(physicalCard);
    }

    @Override
    public int updateAdminPhysicalCard(PhysicalCard physicalCard) {
        // 修改实体卡不允许充值
        if(Objects.isNull(physicalCard) || StringUtils.isEmpty(physicalCard.getPhysicalCardNo())){
            throw new BaseException("qujia-customer","PhysicalCardServiceImpl覆盖实体卡信息请求参数异常");
        }

        // 获取油企名和油站名
        if(Objects.nonNull(physicalCard.getEnterpriseId())) {
            physicalCard.setEnterpriseName(getEnterpriseName(physicalCard.getEnterpriseId()));
        }

        if(StringUtils.isNotEmpty(physicalCard.getStationId())) {
            physicalCard.setStationName(getStationName(physicalCard.getStationId()));
        }

        physicalCard.setUpdateTime(new Date());
        log.info("修改实体卡，PhysicalCardServiceImpl.updatePhysicalCard: [{}]", JSONObject.toJSONString(physicalCard));
        return physicalCardMapper.updateByPrimaryKeySelective(physicalCard);
    }

    @Override
    public int updatePhysicalCardStatus(PhysicalCard physicalCard) {
        if(Objects.isNull(physicalCard) || StringUtils.isEmpty(physicalCard.getPhysicalCardNo())){
            throw new BaseException("qujia-customer","PhysicalCardServiceImpl实体卡冻结注销请求参数异常");
        }
        PhysicalCard card = physicalCardMapper.selectByPrimaryKey(physicalCard.getPhysicalCardNo());
        if(Objects.isNull(card)){
            throw new BaseException("updatePhysicalCardStatus 实体卡不存在");
        }
        physicalCard.setUpdateTime(new Date());
        return physicalCardMapper.updateByPrimaryKeySelective(physicalCard);
    }

    @Override
    public PhysicalCard selectByEnterpriseIdAndPhone(Long enterpriseId,String userPhone) {
        if(Objects.isNull(enterpriseId) || StringUtils.isEmpty(userPhone)){
            throw new BaseException("请求参数不能为空");
        }
        return physicalCardMapper.selectByEnterpriseIdAndPhone(enterpriseId, userPhone);
    }

    @Override
    public void writePhysicalCard(PhysicalCard physicalCard) {
        if(Objects.isNull(physicalCard) || StringUtils.isEmpty(physicalCard.getPhysicalCardNo())){
            throw new BaseException("写卡卡号不能为空");
        }
        PhysicalCard oldPhysicalCard = physicalCardMapper.selectByPrimaryKey(physicalCard.getPhysicalCardNo());
        if(Objects.isNull(oldPhysicalCard)){
            throw new BaseException("该卡号不存在,写卡失败");
        }
        CardBatch cardBatch = cardBatchService.selectCardBatchById(Long.valueOf(oldPhysicalCard.getBatchId()));
        if(StringUtils.isNotEmpty(cardBatch.getPhysicalCardType())){
            if(PhysicalCardTypeEnum.DEK.getValue().equals(cardBatch.getPhysicalCardType())){
                throw new BaseException("定额卡不允许开卡，写卡失败");
            }
        }
        //防止重复建卡
        if(Objects.nonNull(oldPhysicalCard.getEnterpriseId()) || StringUtils.isNotEmpty(oldPhysicalCard.getStationId())){
            throw new BaseException("请勿重复写卡,写卡失败");
        }

        Enterprise enterprise = enterpriseService.selectEnterpriseById(physicalCard.getEnterpriseId());
        if(Objects.isNull(enterprise)){
            throw new BaseException("油企不存在");
        }
        physicalCard.setEnterpriseName(enterprise.getEnterpriseName());

        Station station = stationService.selectStationById(Long.valueOf(physicalCard.getStationId()));
        if(Objects.isNull(station)){
            throw new BaseException("油站不存在");
        }
        physicalCard.setStationName(station.getStationName());

        int i = physicalCardMapper.updateByPrimaryKeySelective(physicalCard);
        if(i <= 0){
            throw new BaseException("写卡失败");
        }
    }

    @Override
    public List<Map<String, Object>> getStationList(Long stationId) {
        Station station = stationService.selectStationById(stationId);
        if(Objects.isNull(station)){
            throw new BaseException("油站不存在");
        }
        if(Objects.isNull(station.getEnterpriseId())){
            throw new BaseException("该油站未绑定油企");
        }
        List<Station> stationList = stationService.selectStationListByEnterpriseId(station.getEnterpriseId());
        if(CollectionUtils.isEmpty(stationList)){
            return null;
        }
        List<Map<String,Object>> list = new ArrayList<>();
        for(Station newStation : stationList){
            Map<String,Object> map = new HashMap<>();
            map.put("stationId",newStation.getStationId());
            map.put("stationName",newStation.getStationName());
            list.add(map);
        }
        return list;
    }

    /**
     * 充值 新增卡时充值金额=实体卡面额
     * 修改覆盖卡时不允许充值
     * */
    private void recharge(PhysicalCard physicalCard){
        // 充值还要添加充值记录
        PhysicalCardBalance physicalCardBalance = new PhysicalCardBalance();
        // 充值金额
        physicalCardBalance.setAmount(physicalCard.getPhysicalCardAmount());
        physicalCardBalance.setPhysicalCardNo(physicalCard.getPhysicalCardNo());
        physicalCardBalance.setEnterpriseId(physicalCard.getEnterpriseId());
        physicalCardBalance.setEnterpriseName(physicalCard.getEnterpriseName());
        physicalCardBalance.setStationId(physicalCard.getStationId());
        physicalCardBalance.setStationName(physicalCard.getStationName());
        // 充值之后的实体卡面额
        physicalCardBalance.setBalanceAmount(physicalCard.getPhysicalCardAmount());
        physicalCardBalance.setStatus(BalanceStatusEnum.SUCCESS.getCode());
        physicalCardBalance.setBalanceType(BalanceTypeEnum.RECHARGE.getValue());
        physicalCardBalanceService.addPhysicalCardBalance(physicalCardBalance);
    }

    private String getEnterpriseName(Long enterpriseId){
        Enterprise enterprise = enterpriseService.selectEnterpriseById(enterpriseId);
        return enterprise.getEnterpriseName();
    }

    private String getStationName(String stationIds){
        String[] strings = stationIds.split(",");
        String stationName = "";
        for (String s : strings){
            Station station = stationService.selectStationById(Long.valueOf(s));
            stationName = stationName + station.getStationName() + ",";
        }
        stationName = stationName.substring(0,stationName.length() - 1);
        return stationName;
    }

    /**创建空卡*/
    @Async("threadPoolTaskExecutor")
    @Override
    public void createEmptyCard(CardBatch cardBatch) {
        int cardNum = cardBatch.getCardNum();
        String batchNo = cardBatch.getBatchNo();
        Integer startNum = cardBatch.getWriteNum();
        while (cardNum > 0){
            if(startNum >= 100000){
                throw new BaseException("超出卡数量限制");
            }
            String physicalCardNo = batchNo + String.format("%05d",startNum);
            PhysicalCard oldPhysicalCard = physicalCardMapper.selectByPhysicalCardNo(physicalCardNo);
            if(Objects.nonNull(oldPhysicalCard)){
                startNum++;
                continue;
            }
            PhysicalCard physicalCard = new PhysicalCard();
            physicalCard.setPhysicalCardNo(physicalCardNo);
            physicalCard.setSecretKeyA(SECRET_KEY_A);
            physicalCard.setSecretKeyB(SECRET_KEY_B);
            physicalCard.setCreateTime(new Date());
            physicalCard.setBatchId(cardBatch.getId().toString());
            physicalCard.setCardType(cardBatch.getBatchType());
            if(PhysicalCardTypeEnum.DEK.getValue().equals(cardBatch.getPhysicalCardType())){
                physicalCard.setPhysicalCardAmount(Objects.nonNull(cardBatch.getPhysicalCardAmount()) ? cardBatch.getPhysicalCardAmount() : BigDecimal.ZERO);
                //定额卡增加充值记录
                PhysicalCardBalance physicalCardBalance = getPhysicalCardBalance(cardBatch,physicalCard);
                physicalCardBalance.setPhysicalCardNo(physicalCardNo);
                physicalCardBalance.setBalanceType(BalanceTypeEnum.RATION_RECHARGE.getValue());
                physicalCardBalance.setPayment(PhysicalCardPaymentEnum.MANUAL_ADD.getValue());
                physicalCardBalanceService.addPhysicalCardBalance(physicalCardBalance);
            }
            physicalCardMapper.insertSelective(physicalCard);
            cardNum--;
        }
    }

    //定额卡新增充值记录
    private PhysicalCardBalance getPhysicalCardBalance(CardBatch cardBatch,PhysicalCard physicalCard){
        PhysicalCardBalance physicalCardBalance = new PhysicalCardBalance();
        physicalCardBalance.setEnterpriseId(cardBatch.getEnterpriseId());
        physicalCardBalance.setEnterpriseName(cardBatch.getEnterpriseName());
        physicalCardBalance.setStationId(cardBatch.getStationId());
        physicalCardBalance.setStationName(cardBatch.getStationName());
        physicalCardBalance.setAmount(Objects.nonNull(cardBatch.getPhysicalCardAmount()) ? cardBatch.getPhysicalCardAmount() : BigDecimal.ZERO);
        physicalCardBalance.setBalanceAmount(Objects.nonNull(cardBatch.getPhysicalCardAmount()) ? cardBatch.getPhysicalCardAmount() : BigDecimal.ZERO);
        physicalCard.setEnterpriseId(cardBatch.getEnterpriseId());
        Enterprise enterprise = enterpriseService.selectEnterpriseById(cardBatch.getEnterpriseId());
        physicalCard.setEnterpriseName(Objects.nonNull(enterprise) ? enterprise.getEnterpriseName() : null);
        physicalCard.setStationId(cardBatch.getStationId());
        physicalCard.setStationName(getStationName(cardBatch.getStationId()));
        return physicalCardBalance;
    }

    @Override
    public List<PhysicalCard> selectPhysicalCardListByBatchId(String batchId) {
        return physicalCardMapper.selectPhysicalCardListByBatchId(batchId);
    }

    @Override
    public Boolean judgePhysicalCard(String physicalCardNo) {
        PhysicalCard physicalCard = physicalCardMapper.judgeByPhysicalCardNo(physicalCardNo);
        if(Objects.nonNull(physicalCard) && StringUtils.isNotEmpty(physicalCard.getPhysicalCardNo())){
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    @Override
    public PhysicalCard selectFirstNumByBatchId(String batchId) {
        return physicalCardMapper.selectFirstNumByBatchId(batchId);
    }

    @Override
    public List<PhysicalCard> selectWithdrawList(PhysicalCardListDto physicalCardListDto) {
        // 已注销状态
        physicalCardListDto.setCardStatus(CardStatusEnum.LOG_OFF.getCode());
        return physicalCardMapper.selectWithdrawList(physicalCardListDto);
    }

    @Override
    public boolean physicalCardType(PhysicalCard physicalCard) {
        if(Objects.isNull(physicalCard) || StringUtils.isEmpty(physicalCard.getBatchId())){
            return false;
        }
        CardBatch cardBatch = cardBatchService.selectCardBatchById(Long.valueOf(physicalCard.getBatchId()));
        if(Objects.isNull(cardBatch) || StringUtils.isEmpty(cardBatch.getPhysicalCardType())){
            return false;
        }
        if(PhysicalCardTypeEnum.DEK.getValue().equals(cardBatch.getPhysicalCardType())){
            return true;
        }
        return false;
    }

    @Override
    public List<PhysicalCard> selectPhysicalCardByAppUserId(Integer appUserId) {
        return physicalCardMapper.selectPhysicalCardByAppUserId(appUserId);
    }
}
